package com.lz.ovuola.service.impl;

import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.lz.ovuola.entity.UserDo;
import com.lz.ovuola.repository.mysql.impl.UserRepository;
import com.lz.ovuola.service.UserService;
import com.lz.ovuola.service.assembler.UserAssembler;
import com.lz.ovuola.util.annotation.TargetDataSource;
import com.lz.ovuola.util.codec.EncryptionUtils;
import com.lz.ovuola.util.constant.DataSourceConsts;
import com.lz.ovuola.util.constant.RedisCacheConsts;
import com.lz.ovuola.util.exception.BusinessException;
import com.lz.ovuola.util.exception.msg.SysSecurityMsgEnum;
import com.lz.ovuola.util.exception.msg.UserMsgEnum;
import com.lz.ovuola.util.fastdfs.FileUtils;
import com.lz.ovuola.util.redis.RedisTemplateRepository;
import com.lz.ovuola.util.regex.RegexUtils;
import com.lz.ovuola.util.response.ResponseDataPackageUtils;
import com.lz.ovuola.util.threadlocal.UserContextHolder;

/**
 * 
 * @author fz
 *
 */
@Service("userService")
public class UserServiceImpl implements UserService {

	@Resource
	private UserRepository userRepository;

	@Autowired
	private RedisTemplateRepository redisTemplateRepository;

	private static Logger logger = LoggerFactory
			.getLogger(UserServiceImpl.class);

	@TargetDataSource(DataSourceConsts.PRIMARY_DS)
	@Transactional(transactionManager = "transactionManagerDynamic", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = false)
	@Override
	public String save(String userName, String password, String nickName,
			String code, Integer mark, String device) {
		// 手机号格式校验
		if (!RegexUtils.isMobile(userName))
			throw new BusinessException(
					SysSecurityMsgEnum.USER_NAME_FORMAT_IS_WRONG.getStatus(),
					SysSecurityMsgEnum.USER_NAME_FORMAT_IS_WRONG.getMsg());
		// password 校验
		if (!RegexUtils.passwordSatify(password))
			throw new BusinessException(
					UserMsgEnum.PASSWORD_IS_WORNG.getStatus(),
					UserMsgEnum.PASSWORD_IS_WORNG.getMsg());
		// 昵称校验
		if (nickName.length() > SysSecurityConst.NICK_NAME_LENGTH)
			throw new BusinessException(
					UserMsgEnum.NICK_NAME_LENGTH_IS_WORNG.getStatus(),
					UserMsgEnum.NICK_NAME_LENGTH_IS_WORNG.getMsg());
		// 验证码校验
		String smsCode = (String) redisTemplateRepository.get(
				RedisCacheConsts.OVUOLA_SECURITY_NAME_SPACE, userName + mark);
		if (!StringUtils.isNotEmpty(smsCode))
			throw new BusinessException(
					SysSecurityMsgEnum.SMS_CODE_TIME_IS_WRONG.getStatus(),
					SysSecurityMsgEnum.SMS_CODE_TIME_IS_WRONG.getMsg());
		if (!smsCode.equals(code))
			throw new BusinessException(
					SysSecurityMsgEnum.SMS_CODE_IS_WRONG.getStatus(),
					SysSecurityMsgEnum.SMS_CODE_IS_WRONG.getMsg());
		// 手机号已注册
		if (ObjectUtils.notEqual(userRepository.findByUserName(userName), null))
			throw new BusinessException(
					SysSecurityMsgEnum.USER_NAME_IS_REGISTER.getStatus(),
					SysSecurityMsgEnum.USER_NAME_IS_REGISTER.getMsg());
		// 保存
		userRepository.save(new UserDo(userName, EncryptionUtils.md5(password),
				nickName, device));
		// 返回数据

		return ResponseDataPackageUtils.success();
	}

	/**
	 * 绑定设备
	 */
	@TargetDataSource(DataSourceConsts.PRIMARY_DS)
	@Transactional(transactionManager = "transactionManagerDynamic", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = false)
	@Override
	public String saveHardwareEquipment(String hardwareEquipment, Integer id) {

		// 绑定设备编码为空
		if (StringUtils.isBlank(hardwareEquipment)) {
			throw new BusinessException(
					UserMsgEnum.HARDWARD_IS_NULL.getStatus(),
					UserMsgEnum.HARDWARD_IS_NULL.getMsg());
		}

		// 查询用户
		UserDo result = userRepository.findOne(id);
		// 用户存在性
		if (!ObjectUtils.notEqual(result, null)) {
			throw new BusinessException(
					UserMsgEnum.USER_IS_NOT_EXIST.getStatus(),
					UserMsgEnum.USER_IS_NOT_EXIST.getMsg());
		}

		// 用户已经绑定设备
		if (StringUtils.isNotBlank(result.getHardwareEquipment())) {
			throw new BusinessException(
					UserMsgEnum.USER_HARDWARD_IS_EXIST.getStatus(),
					UserMsgEnum.USER_HARDWARD_IS_EXIST.getMsg());
		}

		// 设备已经被绑定
		if (ObjectUtils
				.notEqual(userRepository
						.findByHardwareEquipment(hardwareEquipment), null)) {
			throw new BusinessException(
					UserMsgEnum.HARDWARD_IS_BIND.getStatus(),
					UserMsgEnum.HARDWARD_IS_BIND.getMsg());
		}

		// 绑定设备
		result.setUpdateTime(new Date());
		result.setHardwareEquipment(hardwareEquipment);
		result.setBindingTime(new Date());
		userRepository.save(result);
		// 返回数据
		return ResponseDataPackageUtils.success();
	}

	/**
	 * 解绑设备
	 * 
	 * @param userId
	 * @return
	 */

	@TargetDataSource(DataSourceConsts.PRIMARY_DS)
	@Transactional(transactionManager = "transactionManagerDynamic", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = false)
	public String deleteHardwareEquipment(Integer userId) {
		// 查询
		UserDo result = userRepository.findOne(userId);

		// 用户存在性
		if (!ObjectUtils.notEqual(result, null)) {
			throw new BusinessException(
					UserMsgEnum.USER_IS_NOT_EXIST.getStatus(),
					UserMsgEnum.USER_IS_NOT_EXIST.getMsg());
		}

		// 用户未绑定设备 无需解绑
		if (StringUtils.isBlank(result.getHardwareEquipment())) {
			throw new BusinessException(
					UserMsgEnum.USER_HARDWARD_NOT_BIND.getStatus(),
					UserMsgEnum.USER_HARDWARD_NOT_BIND.getMsg());
		}
		// 返回数据
		result.setUpdateTime(new Date());
		result.setHardwareEquipment(null);
		result.setBindingTime(null);
		userRepository.save(result);
		return ResponseDataPackageUtils.success();
	}

	/**
	 * 修改昵称
	 */
	@TargetDataSource(DataSourceConsts.PRIMARY_DS)
	@Transactional(transactionManager = "transactionManagerDynamic", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = false)
	@Override
	public String updateNickName(String nickName, Integer userId) {

		// 昵称校验
		if (nickName == null
				|| nickName.length() > SysSecurityConst.NICK_NAME_LENGTH)
			throw new BusinessException(
					UserMsgEnum.NICK_NAME_LENGTH_IS_WORNG.getStatus(),
					UserMsgEnum.NICK_NAME_LENGTH_IS_WORNG.getMsg());

		UserDo result = userRepository.findOne(userId);

		// 用户存在性
		if (!ObjectUtils.notEqual(result, null)) {
			throw new BusinessException(
					UserMsgEnum.USER_IS_NOT_EXIST.getStatus(),
					UserMsgEnum.USER_IS_NOT_EXIST.getMsg());
		}
		// 赋值用户信息并更新
		result.setNickName(nickName);
		result.setUpdateTime(new Date());
		userRepository.save(result);
		// 返回信息
		return ResponseDataPackageUtils.success();
	}

	@TargetDataSource(DataSourceConsts.PRIMARY_DS)
	@Transactional(transactionManager = "transactionManagerDynamic", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = false)
	@Override
	public String updateHeadImage(byte[] fileBuff, String fileType)
			throws Exception {
		logger.info("...用户id:{} 图片上传,fileType类型：{}", UserContextHolder.get()
				.getUserId(), fileType);
		String type = "";
		if (StringUtils.isEmpty(type = fileTypeCheck(fileType)))
			return ResponseDataPackageUtils.fail(
					UserMsgEnum.IMAGE_TYPE_IS_WRONG.getStatus(),
					UserMsgEnum.IMAGE_TYPE_IS_WRONG.getMsg());
		UserDo user = userRepository.findOne(UserContextHolder.get()
				.getUserId());
		// 用户存在性
		if (!ObjectUtils.notEqual(user, null)) {
			throw new BusinessException(
					UserMsgEnum.USER_IS_NOT_EXIST.getStatus(),
					UserMsgEnum.USER_IS_NOT_EXIST.getMsg());
		}
		String download = FileUtils.uploadFile(fileBuff, type);
		user.setHeadImage(download);
		userRepository.save(user);
		return ResponseDataPackageUtils.success(UserAssembler
				.getUserAssembler().toDtoHeadImage(user));
	}

	/**
	 * 图片校验
	 * 
	 * @param fileType
	 * @return
	 */
	private String fileTypeCheck(String fileType) {
		if (StringUtils.isEmpty(fileType))
			return null;
		String[] temps = fileType.split("/");
		if (temps.length != 2)
			return null;
		return temps[1];
	}
}
